#include "main.h"
#include "string.h"
#include "math.h"

void convol_layer1_2d(float * input_array, float const * weight, float const * bais, float * output_array, int* N_size);
void leaReLU_1d_v1(float *input_array, float alfa, float *output_array, int* N_size);
void maxpooling_1d(float *input_array, float *output_array, int pool_size, int* N_size);
void dense_NoneActiv_v1(float *input_array, float const *weight, float* output_array, float const * bais, int* N_size);
float dense_Sigmoid_v1(float *input_array, float *weight, float bais, int* N_size);
void model_layer_1(float* input_layer_1, float *output_layerpool_1, int* N_size);
void model_layer_1_v2(float* input_layer_1, float *output_layer_1, int* N_size);
void model_layer_2(float* input_layer_2, float *output_layer_2, int* N_size);
void model_layer_3(float* input_layer_3, float *output_layer_3, int* N_size);
void model_layer_4(float* input_layer_4, float *output_layer_4, int* N_size);
void model_layer_5(float* input_layer_5, float *output_layer_5, int* N_size);
void model_layer_6(float* input_layer_6, float *output_layer_6, int* N_size);
void model_layer_7(float* input_layer_7, float *output_layer_7, int* N_size);
void model_layer_8(float* input_layer_8, float *output_layer_8, int* N_size);
void model_flatten(float* input_flatten, float *output_flatten, int* N_size);
int three_lead_diag(float* signal);


/*	
float output_layer_1[5][2486];				//size: 99440
float output_layer_2[5][1236];				//size: 48440
float output_layer_3[5][612];				//size: 24480
float output_layer_4[10][304];				//size: 24320
float output_layer_5[10][150];				//size: 12000
float output_layer_6[10][74];				//size: 5920
float output_layer_7[10][36];				//size: 2880
float output_flatten[360];					//size: 2880
float output_layer_8[10];					//size: 80
*/



float output_1[12430];
float output_2[12430];

extern float const w_layer_0[];
extern float const b_layer_0;
extern float const input_layer_1[];
float HA301A_Check(float* signal)
{
		int N_size[4];//N,K,L,J
		float output_layer_9=0;
		int signal_type=0;
		int j;
		N_size[0] = 5000;
		N_size[1] = 1;
		N_size[2] = 5;
		N_size[3] = 29;

		//添加的内容，让均值为0
		float meanTemp=0;
		for (j = 0; j < 5000; j++)
		{

			meanTemp = (meanTemp + signal[j]) ;

		}
		meanTemp/=5000;
		for (j = 0; j < 5000; j++)
		{
			signal[j] = signal[j] - meanTemp;
		}
		model_layer_1_v2(&signal[0], output_1, N_size);
		//model_layer_1_v2((float *)input_layer_1, output_1, N_size);			//计算结果： 0.02117076515
		model_layer_2(output_1, output_2, N_size);
		model_layer_3(output_2, output_1, N_size);
		model_layer_4(output_1, output_2, N_size);
		model_layer_5(output_2, output_1, N_size);
		model_layer_6(output_1, output_2, N_size);
		model_layer_7(output_2, output_1, N_size);
		model_flatten(output_1, output_2, N_size);
		model_layer_8(output_2, output_1, N_size);
		output_layer_9 += dense_Sigmoid_v1(output_1, (float *)w_layer_0, b_layer_0, N_size);

		return output_layer_9;
}


void model_layer_7(float* input_layer_7, float *output_layer_7, int* N_size)
{
	extern float const w_layer_7[10][10][3];
	extern float const b_layer_7[10];
	int pool_size = 2;
	float alfa = 0.3;

//	 
	N_size[2] = 10;//L
	N_size[3] = 3;//J


	convol_layer1_2d(input_layer_7, &w_layer_7[0][0][0], &b_layer_7[0], output_layer_7, &N_size[0]);
	leaReLU_1d_v1(output_layer_7, alfa, input_layer_7, &N_size[0]);
	maxpooling_1d(input_layer_7, output_layer_7, pool_size, &N_size[0]);
}

extern float const w_layer_6[10][10][3];
extern float const b_layer_6[10];
void model_layer_6(float* input_layer_6, float *output_layer_6, int* N_size)
{
	int pool_size = 2;
	float alfa = 0.3;

	N_size[2] = 10;//L
	N_size[3] = 3;//J
	convol_layer1_2d(input_layer_6, &w_layer_6[0][0][0], &b_layer_6[0], output_layer_6, &N_size[0]);
	leaReLU_1d_v1(output_layer_6, alfa, input_layer_6, &N_size[0]);
	maxpooling_1d(input_layer_6, output_layer_6, pool_size, &N_size[0]);
}



void model_layer_5(float* input_layer_5, float *output_layer_5, int* N_size)
{
	extern float const w_layer_5[10][10][5];
	extern float const b_layer_5[10] ;
	int pool_size = 2;
	float alfa = 0.3;



//	
	N_size[2] = 10;//L
	N_size[3] = 5;//J

	convol_layer1_2d(input_layer_5, &w_layer_5[0][0][0], &b_layer_5[0], output_layer_5, &N_size[0]);
	leaReLU_1d_v1(output_layer_5, alfa, input_layer_5, &N_size[0]);
	maxpooling_1d(input_layer_5, output_layer_5, pool_size, &N_size[0]);	
}


void model_layer_4(float* input_layer_4, float *output_layer_4, int* N_size)
{
	extern float const w_layer_4[10][5][5];
	extern float const b_layer_4[10];
	int pool_size = 2;
	float alfa = 0.3;


	
	N_size[2] = 10;//L
	N_size[3] = 5;//J


	convol_layer1_2d(input_layer_4, &w_layer_4[0][0][0], &b_layer_4[0], output_layer_4, &N_size[0]);
	leaReLU_1d_v1(output_layer_4, alfa, input_layer_4, &N_size[0]);
	maxpooling_1d(input_layer_4, output_layer_4, pool_size, &N_size[0]);
	
}

void model_layer_3(float* input_layer_3, float *output_layer_3, int* N_size)
{
	extern float const w_layer_3[5][5][13];
	extern float const b_layer_3[5];
	int pool_size = 2;
	float alfa = 0.3;

	N_size[2] = 5;//L
	N_size[3] = 13;//J



	convol_layer1_2d(input_layer_3, &w_layer_3[0][0][0], &b_layer_3[0], output_layer_3, &N_size[0]);
	leaReLU_1d_v1(output_layer_3, alfa, input_layer_3, &N_size[0]);
	maxpooling_1d(input_layer_3, output_layer_3, pool_size, &N_size[0]);
}


void model_layer_2(float* input_layer_2, float *output_layer_2, int* N_size)
{
	extern float const w_layer_2[5][5][15] ;
	extern float const b_layer_2[5];
	int pool_size = 2;
	float alfa = 0.3;


	N_size[2] = 5;//L
	N_size[3] = 15;//J


	convol_layer1_2d(input_layer_2, &w_layer_2[0][0][0], &b_layer_2[0], output_layer_2, &N_size[0]);
	leaReLU_1d_v1(output_layer_2, alfa, input_layer_2, &N_size[0]);
	maxpooling_1d(input_layer_2, output_layer_2, pool_size, &N_size[0]);
	
}


void model_layer_1(float* input_layer_1, float *output_layer_1, int* N_size)
{
	extern float const w_layer_1[5][1][29];
	extern float const b_layer_1[5];
	int pool_size = 2;
	float alfa = 0.3;

	
	convol_layer1_2d(input_layer_1, &w_layer_1[0][0][0], &b_layer_1[0], output_layer_1, &N_size[0]);
	leaReLU_1d_v1(output_layer_1, alfa, input_layer_1, &N_size[0]);
	maxpooling_1d(input_layer_1, output_layer_1, pool_size, &N_size[0]);

}

static float temp_array[4972];
void model_layer_1_v2(float* input_layer_1, float *output_layer_1, int* N_size)
{
	extern float const w_layer_1[5][1][29];
	extern float const b_layer_1[5];
	float alfa = 0.3;

	int _N, _K, _J, _L;
	_N = N_size[0];
	_K = N_size[1];
	_J = N_size[3];
	_L = N_size[2];	

	int i, j, k, l;
	float temp;

	for (i = 0; i<_L; i++)      //第i个卷积核的运算，输出信号第i行 
	{

		for (j = 0; j<_N - _J + 1; j++) //输出信号第i维度第j个元素的值；从输入信号的第i行 第j个元素开始相乘  
		{
			temp = b_layer_1[i];
			for (k = 0; k<_K; k++)   //第i个卷积核的第k行；输入信号的第k行 
			{
				for (l = 0; l<_J; l++) //第i个卷积核的第k行的；输入信号的第j+k个元素 
				{
					temp += w_layer_1[i][k][l] * input_layer_1[_N*k + j + l];
				}
				
			}
			if (temp>0) temp_array[j] = temp; else  temp_array[j] = temp*alfa;
			


			if (j % 2)
			{
				if (temp_array[j] >= temp_array[j - 1])
				{
					output_layer_1[i * 2486 + (int)j / 2] = temp_array[j];
				}
				else
				{
					output_layer_1[i * 2486 + (int)j / 2] = temp_array[j - 1];
				}
			}

		}

	}
	N_size[0] = (_N - _J + 1)/2;
	N_size[1] = _L;

}



void convol_layer1_2d(float * input_array, float const * weight, float const * bais, float * output_array, int* N_size)
{
	/*
	输入：
	input_array：输入信号, float input_array[_K][_N];表示K个N长度的信号；
	weight:卷积核系数，三维数组， float weight[_L][_K][_J]表示L个卷积核，每个卷积核的长度为_J,宽度为_K；

	bais:偏移，长度为L
	输出：
	output_array：输出矩阵；_L个长度为N-J+1的信号；

	函数功能：
	卷积运算
	*/

	int _N, _K, _J, _L;
	_N = N_size[0];
	_K = N_size[1];
	_J = N_size[3];
	_L = N_size[2];

	int i, j, k, l;
	float temp;

	for (i = 0; i<_L; i++)      //第i个卷积核的运算，输出信号第i行 
	{

		for (j = 0; j<_N - _J + 1; j++) //输出信号第i维度第j个元素的值；从输入信号的第i行 第j个元素开始相乘  
		{
			temp = bais[i];
			for (k = 0; k<_K; k++)   //第i个卷积核的第k行；输入信号的第k行 
			{
				for (l = 0; l<_J; l++) //第i个卷积核的第k行的；输入信号的第j+k个元素 
				{
					temp += weight[i*_J*_K + k*_J + l] * input_array[_N*k + j + l];
				}
			}
			
			output_array[i*(_N - _J + 1) + j] = temp;
		}
		
	}
	N_size[0] = _N - _J + 1;
	N_size[1] = _L;

}
void leaReLU_1d_v1(float *input_array, float alfa, float *output_array, int* N_size)
{
	/*
	输入：input_array：输入信号,三维数组，大小{M,N,K}；
	input_array_size：输入信号的大小，{M,N,K}；
	alfa：leakRelu的系数；
	output_array：输出矩阵；大小与输入矩阵相同；
	函数功能：
	f(x) = alpha * x for x < 0,
	f(x) = x for x >= 0
	*/
	int i, j;
	float c;
	for (i = 0; i<N_size[1]; i++)
	{
		for (j = 0; j<N_size[0]; j++)
		{
			c = input_array[i*N_size[0] + j];
			if (c>0) output_array[i*N_size[0] + j] = c; else  output_array[i*N_size[0] + j] = c*alfa;
			
		}
		
	}

}

void maxpooling_1d(float *input_array, float *output_array, int pool_size, int* N_size)
/*
输入：input_array，输入信号，长度为N，维度为K；
layer2_size,用于存放输出信号的shape的结构体，包含了两个int变量；{int _N;//信号长度  int _K;//卷积核大小行数为_K}
pool_size：poolingsize的大小；
输出：
output_array：输出信号，长度为N/pool_size,维度为K；
功能：
实现maxpooling运算；
*/
{
	int i, j, k;
	float temp;
	int _K;
	int _N;
	_K = N_size[2];
	_N = N_size[0] / pool_size;
	for (i = 0; i<_K; i++)
	{
		for (j = 0; j<_N; j++)
		{
			temp = input_array[_N*pool_size*i + pool_size*j];
			for (k = 0; k<pool_size; k++)
			{
				if (temp<input_array[_N*pool_size*i + pool_size*j + k])
				{
					temp = input_array[_N*pool_size*i + pool_size*j + k];
				}
			}
			output_array[_N*i + j] = temp;
			
		}
		

	}
	N_size[0] = _N;
	N_size[1] = _K;
}
void dense_NoneActiv_v1(float *input_array, float const *weight, float* output_array, float const * bais,int* N_size)
/*
输入：input_array，输入信号，长度为N；
weight:变换系数 W;
bais:偏置 b;

输出：
output_array：输出信号，长度为L；
功能：
output_array=f(W*input_array+b)，其中 f(x)=x；
*/

{
	int i, j;
	float temp;
	int N = N_size[0];
	int L = N_size[3];
	for (i = 0; i<L; i++)
	{
		temp = bais[i];
		for (j = 0; j<N; j++)
		{
			temp += input_array[j] * weight[i*N + j];
		}
		output_array[i] = temp;
	}

}

float dense_Sigmoid_v1(float *input_array, float *weight,  float bais, int* N_size)
/*
输入：input_array，输入信号，长度为N；
weight:变换系数 W;
bais:偏置 b;

输出：
output_array：输出信号，长度为L；
功能：
output_array=f(W*input_array+b)，其中 f(x)=1/(1+exp(-x))；
*/

{
	int i;
	float temp = bais;
	float output_array;
	int N = N_size[0];
	
	for (i = 0; i<N; i++)
	{
		
		temp += input_array[i] * weight[i];
		
		output_array= 1 / (1 + (exp(-temp)));
	}
	return output_array;
}


void model_flatten(float* input_flatten, float *output_flatten,int* N_size)
{
	int i, j;
	float temp;
	
	for (j = 0; j < 36; j++)
		for (i = 0; i < 10; i++)
		{
		temp = input_flatten[i*36+j];
		*output_flatten= temp;
		output_flatten++;
	
		}
	N_size[0] = 360;
	N_size[3] = 10;
}


void model_layer_8(float* input_layer_8, float *output_layer_8, int* N_size)
{
	extern float const w_layer_8[10][360];
	extern float const b_layer_8[10];	
	//float output_midd_layer8[360];
	float alfa = 0.3;
	int i;
	
	dense_NoneActiv_v1(input_layer_8, &w_layer_8[0][0], output_layer_8, &b_layer_8[0], &N_size[0]);
	leaReLU_1d_v1(output_layer_8, alfa, input_layer_8, &N_size[0]);
	for(i=0;i<360;i++)
		output_layer_8[i]=input_layer_8[i];
	
	N_size[0] = 10;//N
	N_size[1] = 1;//K
	N_size[2] = 1;
	N_size[3] = 1;
}
